folditfandomcom-20200222-history
Lua Scripting Tutorial (Advanced)
Introduction This tutorial is for more experienced programmers, giving some information about functions and tables. Functions - Using and declaring If you already did a shake, wiggle or just printed out a text by script, you have already used (called) a function. But in addition to just using them, you can even create your own functions. Using a function (and declaring it later), you need two things: A function name. This will allow us to call the function in the main program (or another function) by it's name when we need it. Function parameters (arguments). These are the variables, values (constants) or tables the function has to work with. In the declaration, they are put in braces after the function's name. When using several arguments in a function, they are separated by comma. If arguments are not needed, you still have to write the braces, so Lua can see that this is a function, and not a variable. print("Hello") Here, we call the function named print with only one argument - the constant expression "Hello". outputtext="Hello" print(outputtext) In this example, our print-function gets the variable outputtext as argument. Since now, we just used a defined function. It is time to create our own one: function print2(a,b) print("A contents:",a) print("B is:",b) end a="Hello" b="World" print2(a,b) Here, we defined the function print2 with two arguments, a and b. Inside our function, we call the function print twice, to show the content of our arguments. You can also see, that the print function also accepts more than one argument, and that we can use functions within functions. To remember, we could also call our function with constants: function print2(a,b) print("A contents:",a) print("B is:",b) end print2("Hello","World") This would give the same result. Functions - Alias-names of variables By using arguments, you don't need the same names for you variables within functions: function print2(c,d) print("A contents:",c) print("B is:",d) end a="Hello" b="World" print2(a,b) Compare the code with the second one before. It does the same job, but we changed variable names in the function section. We still feed the variables a and b as arguments into the function: a="Hello" b="World" print2(a,b) But in our function declaration, what was called a before is now called c, b is called d. The text to print is still the same: function print2(c,d) print("A contents:",c) print("B is:",d) end The possibility of using alias-names has some advantages: You don't need to change variable names in any function sections, when you: write a new program and decide to use other variable names than before in the code which is calling the function copy a function from a user who works with other variable names call the function more than one time in a code, working on different variables each call But take care! Aliasing only works on variables, if they are submitted as arguments in a function call by their initial names and in the argument list of the function declaration by their alias-names! Functions - scope of global and local variables inside and outside If a variable name within a function is not mentioned as argument at function begin, it is a global variable. If the keyword local is even put before it, it is a local variable. The expressions global and local describe the scope of variables. In our example before, you can say that c has a local content of a, and d has a local content of b. Local, because the values of c and d only exist within the function, outside those variables don't have these values. Outside the function the values are still stored in the variables a and b. Let's see this in a more slim example, at first with a local variable. Slim, because now, we won't be using any arguments to submit values: function test() local a=5 print ("A at function call is:",a) end print("A before function call is:",a) test () print("A after function call is:",a) This should result: A before function call is: nil A at function call is: 5 A after function call is: nil You can see, that outside the function a is nil, as we didn't set a value there for it. Inside the function, using the keyword local, another variable (also called a) is created, we set this to 5. When leaving the function, the other (older) variable a is used again which still has nil information. The local variable a within the function is not visible outside the function, The local variable a outside the function is not visible inside the function. Let's see what happens if we remove the expression local, so we will now use a global variable: function test() a=5 print ("A at function call is:",a) end print("A before function call is:",a) test () print("A after function call is:",a) This should result: A before function call is: nil A at function call is: 5 A after function call is: 5 At start, a hasn't got any value again, as it is not mentioned before function call. But inside the function, the keyword local is missing this time, so no new variable a is created. Variable a inside the function is the same as outside and set to 5. So, when the function is left, it still has the value of 5. Here, one global variable a is visible inside and outside the function. It is up to you to decide, if you want to use global (so you needn't submit them as arguments) or local variables. But as you can imagine, this can cause problems: function count3() local i=0 while i<3 do i=i+1 print("And i inside function is:",i) end end local i=0 while i<2 do i=i+1 print("I outside function is:",i) count3() end This should result: I outside function is: 1 And i inside function is: 1 And i inside function is: 2 And i inside function is: 3 I outside function is: 2 And i inside function is: 1 And i inside function is: 2 And i inside function is: 3 We have got two loops: One is counting from 1 to 2 and calling a function named count3, and in this function, we have a loop counting from 1 to 3. Both loops (outside and inside the function) are using variable i to count. No problem so far. But let's see what happens, if we remove the keyword local: function count3() i=0 while i<3 do i=i+1 print("And i inside function is:",i) end end i=0 while i<2 do i=i+1 print("I outside function is:",i) count3() end Now, we only have: I outside function is: 1 And i inside function is: 1 And i inside function is: 2 And i inside function is: 3 This happens, because variable i is overwritten inside the function, and when the loop inside the function is finished, i has the value 3. As the function is left, i still has value 3, because it is a global variable and the old value for the outer loop isn't fetched. But the loop outside the function is programmed to count to 2, and i is already over this value! So, the outer loop finishes earlier as planned. I tried this also with loops using the for-command with and without using the expression local, it didn't make a difference. Both versions gave the same result as the first example. I guess, for-loops create their own local variables in memory when using functions, but I wouldn't bet on it in a complex program. My advice is: Whenever you use temporary variables (in loops or for intermediate result values for example), write local before them! You can use global variables for basic information, which should be available everywhere, like Puzzle Score, Number of Segments, information about bands or saveslots. When you use arguments, you are always on the safe side, as you can quickly see which variables are feeded into the function and (if necessary) which values of them are changed. Functions - Accidentally created new variables and debugging With this information you have now, at this point a tip for debugging: Maybe sometimes you accidentally create and use global variables without knowing it. Why? Because of a typical behavior of most scripting languages (as Lua is): In scripting languages, you don't need to declare variables before, you can directly use them. If their name appears the first time, the scripting language automatically assigns: With this variable containing nil, computing with it won't work anymore, you just will be able to compare it with other variables/values and check if both of them are equal or unequal. Let's prove this with an example: function PlusOne() print ("A+1 is:",a+1) end a=1 PlusOne() The result is: A+1 is: 2 The content of the global variable a is also visible in the function, so we can add 1 to it in the print-command. Let's suppose, in the function we accidentally typed a as capital, not as small letter: function PlusOne() print ("A+1 is:",A+1) end a=1 PlusOne() This gives the following error: ERROR: "function PlusOne()...":2: attempt to perform arithmetic on global 'A' (a nil value) For Lua, a is not the same as A, Lua is case-sensitive. So, in addition to the existing variable a already having a value, it created a new variable A with the default value nil. But to nil, we can't add 1. This means, if you get an error that a variable is nil, but you did use it before, you maybe misspelled it or wrote a letter in the wrong case. < And now you know, what is happening internally and why. Functions - Returning values So, we submitted values into a function as constant expressions or by using local/global variables, we've read the variables' values inside the function or manipulated them. But functions can also create new values and return them: ... to be continued... Tables Tables are like drawers of a cupboard. They can contain a set of variables, values or other tables, you can even mix these different contents. ... to be continued... Reference For the original source of information and other examples, go to this address: Lua 5.1 Reference Manual Category:script tutorial